/*
 *  scoreBoard - BoardModel.h
 *  Copyright 2011 W. Reckman. All rights reserved.
 */
#ifndef BOARD_MODEL_H
#define BOARD_MODEL_H

#include <vector>
#include "ofTypes.h"
#include "ofImage.h"
#include "BalanceMeter.h"
#include "Settings.h"
#include "Utils.h"

class ScoreBoardApp;
class PlayerHead;


class BoardModel {
public:
	//NOTE: PlayerInfo is declared here to avoid circular dependencies
	struct PlayerInfo {
		PlayerInfo()
		: topImagePath( 0 ), bottomImagePath( 0 )
		{}
		
		int month, day;
		int hours, minutes, seconds;
		int cultureTgt, industryTgt;
		int id;
		string* topImagePath;
		string* bottomImagePath;
		ofColor color;
		int goodPickups, badPickups;
	};
	
	struct EndGameStat {
		int gameNum;
		float balance;
		PlayerHead* winner;
	};
	
	bool p0Colliding; //TEMP
	
	enum NEAR_LANE { NL_PREV_X, NL_NEXT_X, NL_PREV_Y, NL_NEXT_Y };
	
	typedef std::vector<PlayerHead*> vec_PlayerHeadP;
	typedef std::vector<int> vec_int;
	typedef std::vector<EndGameStat> vec_EndGameStat;
	typedef std::vector<ofImage*> vec_ofImageP;
	
	static const int BALANCE_MAX;
	static const float PLAYER_IMAGE_DIMENSION_RATIO;
	static const float PLAYER_TOP_TO_TOTAL_RATIO;
	static const float LANE_THICKNESS;
	
	
	explicit BoardModel( ScoreBoardApp& appRef_ );
	~BoardModel();
	
	void setup();
	void update();
	
	static const ofColor& getPlayerColor( int playerIdx_, PLAYER_COLOR_BRIGHTNESS brightness_ = PCB_NORMAL );
	
	float getTime() const;
	int getCurrentGameNum() const;
	const vec_int& getRowLanes() const;
	const vec_int& getColumnLanes() const;
	const ofRectangle& getBoundingBox() const;
	const vec_PlayerHeadP& getPlayerHeads() const;
	vec_PlayerHeadP& getPlayerHeads();
	const PlayerHead* getPlayerHead( int index_ ) const;
	PlayerHead* getPlayerHead( int index_ );
	const vec_EndGameStat& getEndGameStats() const;
	const BalanceMeter& getBalanceMeter() const;
	BalanceMeter& getBalanceMeter();
	
	int getBasePlayerSpeed() const;
	int getBaseBiteSpeed() const;
	int getPlayerYSubtract() const;
	//int getStageLaneBottomY() const;
	int getBalanceStepPlayer() const;
	int getBalanceStepGlobal() const;
	
	const ofPoint& getPlayerDrawSize() const;
	
	//void addBalance( int val_, BALANCE_KIND kind_ );
	void setBalance( float balance_ );
	void changeGameState( GAME_STATE oldState_, GAME_STATE newState_ );
	
	PlayerHead* createPlayerHead( const PlayerInfo& info_ );
	
	bool dirCoordsAreOnGrid( const ofPoint& c_, DIRECTION dir, int laneMargin_ = 0, int intersectMargin_ = 0 ) const;
	
	bool generateRandomPositionOnGrid( ofPoint& pos_ ) const;
	
	int getNearLane( const GridPoint<int>& p_, NEAR_LANE which_, bool returnIndex_ ) const;
	bool fillInLaneIndices( GridPoint<int>& gp_, int laneMargin_, bool fixCoords_ = false ) const;
	
	bool playerInfosEqual( const BoardModel::PlayerInfo& p1, const BoardModel::PlayerInfo& p2 ) const;
	
private:
	const Settings& s;
	ScoreBoardApp& appRef;
	
	vec_int lutRows, lutColumns;
	ofRectangle boundingBox;
	ofPoint playerDrawSize;
	
	float gameTime;
	int currentGameNum;
	GAME_STATE gameState;
	
	vec_PlayerHeadP playerHeads;
	vec_EndGameStat endGameStats;
	BalanceMeter balance;
	
	int basePlayerSpeed;
	int baseBiteSpeed;
	int playerYSubtract;
	//int stageLaneBottomY;
	
	void setWinnerMovePath( PlayerHead* ph );
	void initLookupTables();
};

#endif /* ! GAME_MODEL_H */
